package com.boarsoft.boar.dir.action;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.boarsoft.bean.LogonI;
import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.boar.BaseConfig;
import com.boarsoft.boar.common.Constants;
import com.boarsoft.boar.common.TreeNode;
import com.boarsoft.boar.dir.DirBiz;
import com.boarsoft.boar.dir.bean.DirTreeNode;
import com.boarsoft.boar.entity.DirInfo;
import com.boarsoft.boar.sys.SysPowerBiz;
import com.boarsoft.common.Util;
import com.boarsoft.common.util.JsonUtil;
import com.boarsoft.web.login.Logined;

public class TreeAction {
	private static final Logger log = LoggerFactory.getLogger(TreeAction.class);

	@Autowired
	protected DirBiz dirBiz;
	@Autowired
	protected SysPowerBiz sysPowerBiz;

	public String get(String id) {
		DirInfo d = dirBiz.get(id);
		return JsonUtil.from(d);
	}

	/**
	 * 返回这个路径上的所有节点及其子节点
	 * 
	 * @return
	 */
	public Map<String, Object> get2(String id) {
		DirInfo d = (DirInfo) dirBiz.get(id);
		String path = d.getPath();
		List<TreeNode> tnLt = null;
		List<TreeNode> pLt = null;
		String pp = null;
		StringBuilder sb = new StringBuilder();
		List<String> idLt = new LinkedList<String>();
		idLt.add(id);// 倒序放入ID
		do {
			List<DirInfo> diLt = dirBiz.listByPath(path);
			tnLt = new ArrayList<TreeNode>();
			for (DirInfo a : diLt) {
				TreeNode tn = new DirTreeNode(a);
				if (pLt != null && pLt.size() > 0) {
					sb.setLength(0);
					sb.append(a.getPath()).append("/").append(a.getCode());
					if (sb.toString().equals(pp)) {
						idLt.add(a.getId());
						tn.setChildren(pLt);
						pLt = null;
					}
				}
				tnLt.add(tn);
			}
			pLt = tnLt;
			pp = path;
			path = path.substring(0, path.lastIndexOf("/"));
		} while (!"".equals(path));
		//
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("success", true);
		m.put("keys", idLt);
		m.put("list", tnLt);
		return m;
	}

	/**
	 * 查询树中当前节点下的子节点，在左侧上上显示，不需要分页
	 * 
	 * @return
	 */
	public ReplyInfo<Object> list(@Logined LogonI<String> logon, String id) {
		String deptId = logon.getDeptId();
		// List<DirInfo> diLt = dirBiz.list(id, types);
		if ("root".equals(id)) {
			id = BaseConfig.DIR_ROOT;
		}
		List<DirInfo> diLt = dirBiz.list(id);
		// 当id为root时表示初始化登录用户权限，过滤掉没有权限的公司和部门
		List<DirTreeNode> dtnLt = new ArrayList<DirTreeNode>();
		if (!BaseConfig.DIR_ROOT.equals(deptId) && BaseConfig.DIR_ROOT.equals(id)) {
			for (DirInfo dirInfo : diLt) {
				if (dirInfo.getType() == DirInfo.TYPE_COMPANY || dirInfo.getType() == DirInfo.TYPE_DEPT) {
					if (!dirInfo.getId().equals(deptId)) {
						continue;
					}
				}
				dtnLt.add(new DirTreeNode(dirInfo));
			}
		} else {
			for (DirInfo di : diLt) {
				dtnLt.add(new DirTreeNode(di));
			}
		}
		return new ReplyInfo<Object>(true, dtnLt);
	}

	protected ReplyInfo<Object> add(DirInfo o) {
		// 新增应用或其他需要挂在目录树下的信息之前需要先把信息插入dir_info表
		// 检查parent是否存在，取出path拼接
		if ("root".equals(o.getParentId())) {
			o.setParentId(BaseConfig.DIR_ROOT);
		}
		// 设置这个目录在目录树上的路径
		if (BaseConfig.DIR_ROOT.equals(o.getParentId())) {
			o.setPath("/");
			o.setLevel(1);
		} else {
			DirInfo p = dirBiz.get(o.getParentId());
			o.setLevel(p.getLevel() + 1);
			if ("/".equals(p.getPath())) {
				o.setPath(String.format("%s%s", p.getPath(), p.getId()));
			} else {
				o.setPath(String.format("%s/%s", p.getPath(), p.getId()));
			}
		}
		o.setStatus(DirInfo.STATUS_INUSE);
		//
		ReplyInfo<Object> ro = dirBiz.add(o);// 此方法将完成相关数据的处理，详见说明
		if (ro.isSuccess()) {
			DirTreeNode dtn = new DirTreeNode((DirInfo) ro.getData());
			return new ReplyInfo<Object>(true, dtn);
		}
		return new ReplyInfo<Object>(ro.getData());
	}

	protected ReplyInfo<Object> update(DirInfo a) {
		// 只能改DirInfo
		DirInfo o = dirBiz.get(a.getId());
		o.setCode(a.getCode());
		o.setName(a.getName());
		o.setMemo(a.getMemo());
		// o.setPath(path); //path是由code决定
		// update方法需判断code是否改变，一旦改变，需修改子节点的path
		ReplyInfo<Object> ro = dirBiz.update(o);// 此方法将完成相关数据的处理，详见说明
		if (ro.isSuccess()) {
			DirTreeNode dtn = new DirTreeNode((DirInfo) ro.getData());
			return new ReplyInfo<Object>(true, dtn);
		}
		return new ReplyInfo<Object>(ro.getData());
	}

	/**
	 * 删除库包、应用、目录、系统、部门、公司 会递归删除待删除目标的子目录 id 被删除的目录id
	 * 
	 * @return
	 */
	public ReplyInfo<Object> delete(String id) {
		try {
			DirInfo d = dirBiz.get(id);
			if (d != null) {
				dirBiz.delete(d);
				//
				String pid = d.getParentId();
				if (Util.strIsNotEmpty(pid)) {
					DirInfo p = dirBiz.get(pid);
					if (p != null) {
						p.setChildCount(p.getChildCount() - 1);
						dirBiz.update(p);
					}
				}
			}
			return ReplyInfo.SUCCESS;
		} catch (Exception e) {
			log.error("Error on delete dir {}", id, e);
			return Constants.REPLY_ERROR_INTERNAL;
		}
	}

	/**
	 * 拷贝指定ID的树节点到指定的目录（parent）下
	 * 
	 * @return
	 */
	public ReplyInfo<Object> copy(String id, String parent) {
		DirInfo od = dirBiz.get(id);
		try {
			this.copy(od, parent);
			return ReplyInfo.SUCCESS;
		} catch (Exception e) {
			log.error("Error on copy tree node: {},to copy to {},Exception is: \n{}", od, parent, e);
			return Constants.REPLY_ERROR_INTERNAL;
		}
	}

	private void copy(DirInfo od, String to) throws Exception {
		if (od.getStatus() < 0) {
			return;
		}
		DirInfo nd = null;
		try {
			nd = dirBiz.copy(od, to);
		} catch (Exception e) {
			log.info("od={},to={}", JSON.toJSONString(od), to);
			e.printStackTrace();
			return;
		}
		if (nd == null) {
			return;
		}
		// 打标识，避免复制递归复制
		nd.setStatus(new Integer(nd.getStatus() * -1).shortValue());
		dirBiz.update(nd);
		//
		if (od.getChildCount() > 0) {
			List<DirInfo> lt = dirBiz.list(od.getId());
			if (lt == null || lt.size() == 0) {
				log.warn("Child count of tree node {}/{}, but the children is missing", od.getId(), od.getName());
				return;
			}
			for (DirInfo cd : lt) {
				this.copy(cd, nd.getId());
			}
		}
		// 重置标识
		nd.setStatus(new Integer(nd.getStatus() * -1).shortValue());
		dirBiz.update(nd);
	}

	public ReplyInfo<Object> move(String id, String parent) {
		DirInfo d = dirBiz.get(id);
		if (d.getStatus() < 0) {
			return Constants.REPLY_WARN_INVALID;
		}
		if (d.getParentId().equals(parent)) {
			return Constants.REPLY_WARN_INVALID;
		}
		try {
			dirBiz.move(d, parent);
			return ReplyInfo.SUCCESS;
		} catch (Exception e) {
			log.error("Error on move tree node {}", d, e);
			return Constants.REPLY_ERROR_INTERNAL;
		}
	}

	/**
	 * 启用应用或系统 根据id更新dir_info表，设置status为 1 （status-应用状态：0：停用，1：启用 ）
	 * 支持批量启用多个应用，多个应用id用英文逗号分隔
	 * 
	 * @return
	 */
	public ReplyInfo<Object> start(String ids) {
		if (dirBiz.start(ids)) {
			return ReplyInfo.SUCCESS;
		}
		return Constants.REPLY_WARN_INVALID;
	}

	/**
	 * 停用应用或系统 根据id更新dir_info表，设置status为 1 （status-应用状态：0：停用，1：启用 ）
	 * 支持批量启用多个应用，多个应用id用英文逗号分隔
	 * 
	 * @return
	 */
	public ReplyInfo<Object> stop(String ids) {
		if (dirBiz.stop(ids)) {
			return ReplyInfo.SUCCESS;
		}
		return Constants.REPLY_WARN_INVALID;
	}
}